package main

import (
    "fmt"
    "reflect"
)

type Book struct {
    Id int
    Name string
    Auth string
}

func (this Book) CallValue()  {
    fmt.Println("Book.CallValue()值调用...")
}

func (this *Book) CallPoint()  {
    fmt.Println("Book.CallValue()指针调用...")
}

func main() {
    book := Book{1, "三体", "刘慈欣"}

    pointType := reflect.TypeOf(&book)
    pointValue := reflect.ValueOf(&book)

    numMethod := pointType.NumMethod()

    for i := 0; i < numMethod; i++ {
        method := pointValue.Method(i)
        // 因为我们的方法没有入参，所以我就定义了一个空的params，如果有入参，就要通过make开辟空间，放入参数了
        var params []reflect.Value
        method.Call(params)
    }
}

func main3() {
    book := Book{1, "三体", "刘慈欣"}

    valueType := reflect.TypeOf(book)
    pointType := reflect.TypeOf(&book)

    numMethod1 := valueType.NumMethod()
    numMethod2 := pointType.NumMethod()

    fmt.Printf("valueType.NumField = %d\n", numMethod1)
    fmt.Printf("pointType.NumField = %d\n", numMethod2)

    for i := 0; i < numMethod1; i++ {
        method := valueType.Method(i)
        fmt.Printf("valueType方法：%s:%s\n", method.Name, method.Type)
    }

    for i := 0; i < numMethod2; i++ {
        method := pointType.Method(i)
        fmt.Printf("pointType方法：%s:%s\n", method.Name, method.Type)
    }
}

func main2() {
    book := Book{1, "三体", "刘慈欣"}

    pointType := reflect.TypeOf(&book)
    pointValue := reflect.ValueOf(&book)

    numField1 := pointType.Elem().NumField()
    numField2 := pointValue.Elem().NumField()

    fmt.Printf("valueType.NumField = %d\n", numField1)
    fmt.Printf("pointValue.NumField = %d\n", numField2)

    for i := 0; i < numField1; i++ {
        field := pointType.Elem().Field(i)
        value := pointValue.Elem().Field(i).Interface()
        fmt.Printf("属性：%s: %v = %v\n", field.Name, field.Type, value)
    }
}

func main1() {
    book := Book{1, "三体", "刘慈欣"}

    valueType := reflect.TypeOf(book)
    pointType := reflect.TypeOf(&book)

    reflect.ValueOf(&book).Elem()

    fmt.Printf("一：valueType.Name = %s, valueType.Kind = %s\n", valueType.Name(), valueType.Kind())
    fmt.Printf("二：pointType.Name = %s, pointType.Kind = %s\n", pointType.Name(), pointType.Kind())
    fmt.Printf("三：pointType.Elem.Name = %s, pointType.Elem.Kind = %s\n", pointType.Elem().Name(), pointType.Elem().Kind())
}
